
#include "ftp_client_commands.h"

int check_command(char *data, int socket, int *quit) {
	char buf[MAXDATA];
	char *cmd, *arguments;
	int recvNbytes, sendNbytes;

	cmd = strtok(data, ARGUMENT_DELIMITER);
	arguments = strtok(NULL, ARGUMENT_DELIMITER);
	if (strcmp(cmd, "quit") == 0)
		*quit = 1;
	else if (strcmp(cmd, "?") == 0)
		print_available_commands();
	else if (strcmp(cmd, "lcd") == 0) {
		return ftp_lcd(arguments);
	} else if (strcmp(cmd, "cd") == 0) {
		return ftp_cd(arguments, socket, buf);
	} else if (strcmp(cmd, "ls") == 0) {

	} else if (strcmp(cmd, "put") == 0) {

	} else if (strcmp(cmd, "get") == 0) {

	} else {

	}
	return 0;
}

void print_available_commands() {
	fprintf(stdout, "Available commands are:\n");
	fprintf(stdout, "ls - List current directory on the remote server\n");
	fprintf(stdout, "lcd <directory> - Change local directory\n");
	fprintf(stdout, "cd <directory> - Change remote directory\n");
	fprintf(stdout, "put <filename> - Copy file from local directory to remote directory\n");
	fprintf(stdout, "get <filename> - Copy file from remote directory to local directory\n");
}

int ftp_lcd(char *directory) {
	int args = check_arguments(directory);
	if (args != 1) {
		fprintf(stderr, "Error in command lcd, expected 1 argument, got %d\n", args);
		return 0;
	}
	if (chdir(directory) == -1) {
		fprintf(stderr, "Error changing to local directory %s\n", directory);
	}
	return 0;
}

int ftp_cd(char *directory, int socket, char *buf) {
	char *ptr;
	int recvNbytes;

	if (directory == NULL) {
		fprintf(stderr, "Command cd expects an argument\n");
		return 0;
	}

	strcpy(buf, FTP_COMMAND_CD);
	ptr = buf + strlen(FTP_COMMAND_CD);
	*ptr = ' ';
	ptr++;
	strcpy(ptr, directory);

	if (send(socket,buf, strlen(buf), 0) == -1) {
		perror("send");
		return 1;
	}
	recvNbytes = recv(socket, buf, MAXDATA - 1, 0);
	buf[recvNbytes] = '\0';
	if (strcmp(buf, FTP_RETURN_OK) != 0) {
		fprintf(stdout, "Error running remote ls command, return code is: %s\n", buf);
		return 0;
	}
	return 0;
}

int ftp_ls(int socket, char *buf, char *arguments) {
	int args, recvNbytes;
	args = check_arguments(arguments);
	if (args != 0) {
		fprintf(stderr, "Error in command ls, expected 0 arguments, got %d\n", args);
		return 0;
	}

	if (send(socket, FTP_COMMAND_CD, strlen(FTP_COMMAND_CD), 0) == -1) {
		perror("send - ls");
		return 1;
	}

	recvNbytes = recv(socket, buf, MAXDATA - 1, 0);
	buf[recvNbytes] = '\0';
	if (strcmp(buf, FTP_RETURN_OK) != 0) {
		fprintf(stdout, "Error running remote ls command, return code is: %s\n", buf);
		return 0;
	} else {
		char *data;
		data = strtok(buf, ARGUMENT_DELIMITER);
		while (data != NULL) {
			fprintf(stdout, "%s", data);
			if (send(socket, FTP_COMMAND_CD, strlen(FTP_COMMAND_CD), 0) == -1) {
				perror("send - ls");
				return 1;
			}

			recvNbytes = recv(socket, buf, MAXDATA - 1, 0);
			buf[recvNbytes] = '\0';
			if (strcmp(buf, FTP_RETURN_OK) != 0) {
				fprintf(stdout, "Error running remote ls command, return code is: %s\n", buf);
				return 0;
			}
			data = strtok(buf, ARGUMENT_DELIMITER);
		}
	}
	return 0;
}

int ftp_put(char *filename, int socket, char *buf) {
	int args = check_arguments(filename);
	int recvNbytes, readbytes;
	char *ptr;
	FILE *ofile;

	if (args != 1) {
		fprintf(stderr, "Error in command put, expected 1 argument, got %d\n", args);
		return 0;
	}

	strcpy(buf, FTP_COMMAND_PUT);
	ptr  = buf + strlen(FTP_COMMAND_PUT);
	*ptr = ' ';
	ptr++;
	strcpy(ptr, filename);
	if (send(socket, buf, strlen(FTP_COMMAND_PUT) + 1 + strlen(filename), 0) == -1) {
		perror("send - put");
		return 1;
	}

	recvNbytes = recv(socket, buf, MAXDATA - 1, 0);
	buf[recvNbytes] = '\0';
	if (strcmp(buf, FTP_RETURN_OK) != 0) {
		fprintf(stdout, "Error running remote put command, return code is: %s\n", buf);
		return 0;
	} else {
		ofile = fopen(filename, "r");
		fseek(ofile, 0, SEEK_SET);
		strcpy(buf, FTP_COMMAND_PUT);
		ptr  = buf + strlen(FTP_COMMAND_PUT);
		*ptr = ' ';
		ptr++;
		readbytes = fread(ptr, sizeof(char), MAXDATA - 1 - strlen(FTP_COMMAND_PUT) - 1, ofile);
		while (readbytes > 0) {
			//TODO: check read error
			if (send(socket, buf, strlen(FTP_COMMAND_PUT) + 1 + readbytes, 0) == -1) {
				perror("send - put");
				fclose(ofile);
				return 1;
			}
			recvNbytes = recv(socket, buf, MAXDATA - 1, 0);
			buf[recvNbytes] = '\0';
			if (strcmp(buf, FTP_RETURN_OK) != 0) {
				fprintf(stdout, "Error running remote put command, return code is: %s\n", buf);
				return 0;
			}
			readbytes = fread(ptr, sizeof(char), MAXDATA - 1 - strlen(FTP_COMMAND_PUT) - 1, ofile);
		}
		fcolse(ofile);
		if (send(socket, FTP_COMMAND_PUT, strlen(FTP_COMMAND_PUT), 0) == -1) {
			perror("send - put");
			return 1;
		}
	}
	return 0;
}

int ftp_get(char *filename, int socket, char *buf) {
	int args = check_arguments(filename);
	int recvNbytes, readbytes;
	char *ptr;
	FILE *ofile;

	if (args != 1) {
		fprintf(stderr, "Error in command put, expected 1 argument, got %d\n", args);
		return 0;
	}

	strcpy(buf, FTP_COMMAND_GET);
	ptr  = buf + strlen(FTP_COMMAND_GET);
	*ptr = ' ';
	ptr++;
	strcpy(ptr, filename);
	if (send(socket, buf, strlen(FTP_COMMAND_GET) + 1 + strlen(filename), 0) == -1) {
		perror("send - put");
		return 1;
	}

	recvNbytes = recv(socket, buf, MAXDATA - 1, 0);
	buf[recvNbytes] = '\0';
	if (strcmp(buf, FTP_RETURN_OK) != 0) {
		fprintf(stdout, "Error running remote get command, return code is: %s\n", buf);
		return 0;
	} else {
		ofile = fopen(filename, "w");
		char *tok;

		do {
			if (send(socket, buf, strlen(FTP_COMMAND_GET) + 1 + strlen(filename), 0) == -1) {
				perror("send - put");
				return 1;
			}

			recvNbytes = recv(socket, buf, MAXDATA - 1, 0);
			buf[recvNbytes] = '\0';

			tok = strtok(buf, ARGUMENT_DELIMITER);
			if (strcmp(tok, FTP_RETURN_OK) != 0) {
				fclose(ofile);
				fprintf(stderr, "Error running remote get command, return code is: %s\n", tok);
				return 0;
			}
			tok = strtok(buf, ARGUMENT_DELIMITER);
			recvNbytes -= 1 + strlen(FTP_RETURN_OK);
			if (fwrite(tok, sizeof(char), recvNbytes, ofile) == -1) {
				fclose(ofile);
				fprintf(stderr, "Error writing to file %s\n", filename);
				return 1;
			}
		} while (recvNbytes > 0);
		fcolse(ofile);
	}
	return 0;
}

int check_arguments(char *data) {
	int args = 1;
	char *tok;

	if (data == NULL)
		return 0;

	tok = strtok(data, ARGUMENT_DELIMITER);
	while (tok != NULL) {
		args++;
		tok = strtok(NULL, ARGUMENT_DELIMITER);
	}
	return args;
}
